# -*- encoding: utf-8 -*-
"""
把文件夹里面的结构转化成html盒子套盒子的结构图
2021年08月04日
by littlefean
"""

import os

# IGNORE_FILES = ["gz", "log", "mca", "dat"]
IGNORE_FILES = []
IMG_FILES = {
    "PNG", "png", "jpg", "JPG", "JPEG", "jpeg", "bmp", "BMP"
}
CODE_FILES = {
    "xml", "txt", "md",
    "java", "c", "h", "cpp", "go",
    "py", "pyi",
    "css", "html", "less", "ts", "js", "wxml", "wxss", "map", "json"
}


def main():
    fPath = r"D:\学习"
    f = Folder.create(fPath)
    fName = fPath.split(os.sep)[-1]
    contentHtmlStr = f.toHtmlStr()
    with open("style\\htmlProjectStyle.css", encoding="utf-8") as f:
        cssContent = f.read()
    htmlStr = f"""<!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta charset="UTF-8">
        <title>{fName}</title>
        <style>
            {cssContent}
        </style>
    </head>

    <body>
    {contentHtmlStr}
    </body>

    </html>
    """
    with open(f"{fName}.html", 'w', encoding='utf-8') as f:
        f.write(htmlStr)


class Folder:
    """文件夹类"""

    def __init__(self, path: str, content: list):
        self.path = path  # 表示文件夹的目录
        self.content = content  # 该文件夹里所含的内容 [Folder, file, file, Folder...] 里面的元素可以是他自己

    @classmethod
    def create(cls, path: str):
        """创建该实例的静态工厂方法"""
        array = os.listdir(path)

        def deep(arr: list, folderName: str):
            nowArr = []  # 当前文件夹里存放列表

            for a in arr:
                ap = path + os.sep + a
                if os.path.isdir(ap):
                    # 文件夹
                    try:
                        folderArr = os.listdir(ap)
                    except PermissionError:
                        # 拒绝访问
                        folderArr = []
                    for i in range(len(folderArr)):
                        folderArr[i] = a + os.sep + folderArr[i]
                    nowArr.append(deep(folderArr, a.split(os.sep)[-1]))
                elif os.path.isfile(ap):
                    # 文件
                    nowArr.append(ap)
            # return nowArr
            return cls(folderName, nowArr)

        res = deep(array, path)
        return cls(res.path, res.content)

    def __str__(self):
        lineStringArr = []
        d = 0
        lineStringArr.append("┃\t" * d + "┏" + f"{'━' * 5}" + f"{self.path}")

        def deep(arr: list, level: int, strArr: list):
            for item in arr:
                if type(item) == Folder:
                    lineStringArr.append("┃\t" * level + "┏" + f"{'━' * 5}" + f"{item.path}")
                    deep(item.content, level + 1, strArr)
                    lineStringArr.append("┃\t" * level + "┗" + f"{'━' * 30}")
                else:
                    name = item.split(os.sep)[-1]
                    lineStringArr.append("┃\t" * level + name)
                ...
            ...

        deep(self.content, d + 1, lineStringArr)
        lineStringArr.append("┃\t" * d + "┗" + f"{'━' * 30}")
        return "\n".join(lineStringArr)

    def toHtmlStr(self, imgShow=True):
        """
        返回该文件夹路径的html标签字符串
        :param imgShow: 是否显示图片的缩略图
        :return:
        """

        def dfs(arr: list, string: str):
            for item in arr:
                if type(item) == Folder:
                    if item.path[0] != ".":  # 忽略隐藏文件夹
                        r = dfs(item.content, "")
                        string += f"<div class='folder'>" \
                                  f"<p class='folderName'>{item.path}</p>" \
                                  f"{r}" \
                                  f"</div>"
                else:
                    name = item.split(os.sep)[-1]
                    arr = name.split(".")
                    if len(arr) > 1 and arr[-1] not in IGNORE_FILES:
                        lineClass = ""
                        # 如果是一个代码文件，那么就统计它的行数
                        if arr[-1] in CODE_FILES:
                            try:
                                with open(item, 'r', encoding='utf-8') as codeFile:
                                    try:
                                        codeLines = len(codeFile.readlines())
                                    except UnicodeDecodeError:
                                        codeLines = 1
                                    codeLines //= 100
                                    lineClass = f'lines{codeLines}'
                            except PermissionError:
                                lineClass = 'lines0'
                        # 如果是一个图片文件，那么就给他添加预览效果
                        if arr[-1] in IMG_FILES and imgShow:
                            pathStr = item.replace(self.path, "").replace("\\", "/")
                            name += f"<img src='.{pathStr}' alt='xxx'>"
                            ...
                        string += f"<div class='file {arr[-1]} {lineClass}'>{name}</div>"
            return f"{string}"

        rr = dfs(self.content, "")
        res = f"<div class='folder'><p class='folderName'>{self.path}</p>{rr}</div>"
        return res

    def __repr__(self):
        return self.path


if __name__ == '__main__':
    main()
